#include "gl_hershey.h"

#include <cstring>
#include <cstdarg>
#include <cstdio>
#include <vector>
#include <gl\glfw.h>
#include <math.h>
#include "simplexFont.h"

HersheyText* HersheyText::_instance = 0x0;

HersheyText* HersheyText::Instance()
{ 
	if( !_instance )
	{
		_instance = new HersheyText();
	}
	return _instance;
}

void HersheyText::moveTo(float x, float y)
{
    moveToX = x;
    moveToY = y;
}

void HersheyText::lineTo(float x, float y)
{	
    glBegin(GL_LINES);
        glVertex2f( moveToX , moveToY );
        glVertex2f( x,y);
    glEnd();
    moveToX = x;
    moveToY = y;
}



void HersheyText::setFont(float w, float h)
{
	textW = w/20; textH = h/20;
}

void HersheyText::glPrintf(const char *format,...)
{
    if (format == NULL) return;
    float sx = moveToX;
    //float sy = moveToY;
    tx=moveToX;
    ty=moveToY;

	std::vector<char> finalText;

    va_list args;
    va_start(args, format);
	// _vscprintf doesn't count terminating '\0' (that's why +1)
	int len = _vscprintf(format, args) + 1;
	finalText.resize(len);

    vsprintf_s(&finalText[0], len, format, args);
    va_end(args);

	for (int i = 0; i < len; i++)
	{
		if( finalText[i] == '\n' )
		{
			tx = sx;
			ty += 20*textH;
		}else{
			int c = (int)finalText[i]-32;

			if(c < 0 || c > 94) continue;
			{
				drawChar( c, textW );
				tx += simplex[c][1]*textW;
			}
		}
	}
    moveToX = sx;
    moveToY = ty;

}

void drawCone(double x0,double y0,double r1,double x1,double y1,double r2)
{
#ifndef M_PI
#define M_PI 3.14159
#endif
	glBegin(GL_POLYGON);
	double ang = M_PI/2+atan2( y0-y1, x0-x1 );
	int segs = 24;
	for(int i=0; i<segs+1; i++){
		double a = ang+i*M_PI/(double)segs;
		double x = cos(a)*r2;
		double y = sin(a)*r2;
		glVertex2d(x1+x,y1+y);
	}
	ang+= M_PI;
	for(int i=0; i<segs+1; i++){
		double a = ang+i*M_PI/(double)segs;
		double x = cos(a)*r1;
		double y = sin(a)*r1;
		glVertex2d(x0+x,y0+y);
	}
	glEnd();

}

void HersheyText::glPrintf( const std::string &text )
{
	if (text.size() == 0) return;
	float sx = moveToX;
	//float sy = moveToY;
	tx=moveToX;
	ty=moveToY;


	for (size_t i = 0; i < text.size(); i++)
	{
		if( text[i] == '\n' )
		{
			tx = sx;
			ty += 20*textH;
		}else{
			int c = (int)text[i]-32;

			if(c < 0 || c > 94) continue;
			{
				drawChar( c, textW );
				tx += simplex[c][1]*textW;
			}
		}
	}
	moveToX = sx;
	moveToY = ty;
}

// TODO make 2D and 3D prinft's use same code?
void HersheyText::glPrintf3D( const char *format,... )
{
	if (format == NULL) return;
	std::vector<char> finalText;

	va_list args;
	va_start(args, format);
	// _vscprintf doesn't count terminating '\0' (that's why +1)
	int len = _vscprintf(format, args) + 1;
	finalText.resize(len);
	vsprintf_s(&finalText[0], len, format, args);
	va_end(args);
	

	float sx = moveToX;
	tx = -len * 0.5f;// * textW;
	ty = 0.f;

	glBegin(GL_LINES);
	for (int i = 0; i < len; i++) {
		if( finalText[i] == '\n' )
		{
			tx = sx;
			ty += 20*textH;
		}else{
			int c = (int)finalText[i]-32;
			if(c < 0 || c > 94) continue;
			{
				drawChar3D( c, textW );
				tx += simplex[c][1]*textW;
			}
		}
	}
	glEnd();
	moveToX = sx;
	moveToY = ty;
}

void HersheyText::drawChar(int c,float scale){
	int verts = (int)simplex[c][0];
	//float spacing = simplex[c][1];

	float radi = 0.9f * scale;
	
	float ax = simplex[c][2];
	float ay = simplex[c][3]; 

	float sx = tx + ax*scale-scale*2.0f;
	float sy = ty - ay*scale+scale*2.0f;
	moveTo(sx,sy);
	int i;
	for( i=4; i<verts*2; i+=2)
	{
		ax = simplex[c][i+0];
		ay = simplex[c][i+1];

		if( int(ax) == -1 || int(ay) == -1)
		{
			sx = tx + simplex[c][i+2] * scale-scale*2.0f;
			sy = ty - simplex[c][i+3] * scale+scale*2.0f;
			moveTo(sx,sy);
		}
		else{
			float ex = tx + ax*scale-scale*2.0f;
			float ey = ty - ay*scale+scale*2.0f;
			//drawCone(sx,sy,radi,ex,ey,radi);
			sx = ex;
			sy = ey;
			lineTo(ex, ey );
		}
	}
	
	float ex = tx+simplex[c][i+0]*scale-scale*2.0f;
	float ey = ty-simplex[c][i+1]*scale+scale*2.0f;
	//drawCone(sx,sy,radi,ex,ey,radi);
	lineTo(ex,ey);
}


void HersheyText::drawChar3D( int c,float scale )
{
	int verts = (int)simplex[c][0];

	float ax = simplex[c][2];
	float ay = simplex[c][3]; 
	float startx = tx + ax*scale-scale*2.0f;
	float starty = ty + ay*scale+scale*2.0f;
	float startz = 0.f;

	int i=0;
	for(i=4; i<verts*2; i+=2)
	{
		ax = simplex[c][i+0];
		ay = simplex[c][i+1];

		if(ax==-1 || ay == -1) 
		{
			startx = tx + simplex[c][i+2]*scale-scale*2.0f;
			starty = ty + simplex[c][i+3]*scale+scale*2.0f;
			startz = 0.f;
		}
		else
		{
			float ex = tx+ax*scale-scale*2.0f;
			float ey = ty+ay*scale+scale*2.0f;
			float ez = 0.f;
			glVertex3f(startx,starty,startz);
			glVertex3f( ex,ey,ez);
			startx = ex;
			starty = ey;
			startz = ez;

		}
	}

	float ex = tx + simplex[c][i+0]*scale-scale*2.0f;
	float ey = ty + simplex[c][i+1]*scale+scale*2.0f;
	glVertex3f(startx,starty,startz);
	glVertex3f( ex,ey,0.f );
}

